package server

import (
	"fmt"
	"go-socks5/pkg/log"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/gin-contrib/static"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
)

type ServerInfo struct {
	Version    string    `json:"version"`
	BindAddr   string    `json:"bindAddr"`
	BindPort   int       `json:"bingPort"`
	EnableAuth bool      `json:"enableAuth"`
	Username   string    `json:"username"`
	Password   string    `json:"password"`
	LogPath    string    `json:"logPath"`
	StartTime  time.Time `json:"startTime"`
}

// DashboardServer HTTP服务器，提供查询在线客户端的API
type DashboardServer struct {
	clientManager *ClientManager
	server        *gin.Engine
	serverInfo    *ServerInfo
	port          int
	username      string
	password      string
	jwtSecret     []byte
}

// NewDashboardServer 创建一个新的 Dashboard 服务器
func NewDashboardServer(port int, username string, password string, clientManager *ClientManager, serverInfo *ServerInfo) *DashboardServer {
	gin.SetMode(gin.ReleaseMode)
	r := gin.New()
	r.Use(gin.Recovery())
	r.Use(corsMiddleware())

	ds := &DashboardServer{
		server:        r,
		port:          port,
		username:      username,
		password:      password,
		clientManager: clientManager,
		serverInfo:    serverInfo,
		jwtSecret:     []byte("go-socks5-dashboard-secret"),
	}
	ds.setupRoutes()
	return ds
}

// corsMiddleware 处理跨域请求
func corsMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type, Content-Length, Accept-Encoding, Authorization")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
			return
		}

		c.Next()
	}
}

// authMiddleware 身份验证中间件
func (ds *DashboardServer) authMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 如果未设置用户名和密码，跳过认证
		if ds.username == "" || ds.password == "" {
			c.Next()
			return
		}

		tokenString := c.GetHeader("Authorization")
		if tokenString == "" {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    401,
				"message": "未授权",
			})
			return
		}

		// 去掉 Bearer 前缀
		if len(tokenString) > 7 && tokenString[:7] == "Bearer " {
			tokenString = tokenString[7:]
		}

		token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
				return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
			}
			return ds.jwtSecret, nil
		})

		if err != nil || !token.Valid {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"code":    401,
				"message": "令牌无效",
			})
			return
		}

		c.Next()
	}
}

// setupRoutes 设置API路由
func (ds *DashboardServer) setupRoutes() {
	// 登录路由不需要认证
	ds.server.POST("/api/v1/login", ds.login)
	// 添加静态文件服务
	ds.server.Use(static.Serve("/dashboard", static.LocalFile("../web/dist", true)))

	// 需要认证的API路由组
	api := ds.server.Group("/api/v1")
	// 加载静态资源
	api.Use(ds.authMiddleware())
	{
		api.GET("/server/info", ds.getServerInfo)
		api.GET("/clients", ds.getAllClients)
		api.GET("/clients/:id", ds.getClientByID)
		api.GET("/clients/stats", ds.getClientsStats)
	}

	// 处理所有未匹配的路由，发送给前端路由处理
	ds.server.NoRoute(func(c *gin.Context) {
		accept := c.Request.Header.Get("Accept")
		flag := strings.Contains(accept, "text/html")
		if flag {
			content, err := os.ReadFile("../web/dist/index.html")
			if (err) != nil {
				c.Writer.WriteHeader(404)
				c.Writer.WriteString("Not Found")
				return
			}
			c.Writer.WriteHeader(200)
			c.Writer.Header().Add("Accept", "text/html")
			c.Writer.Write((content))
			c.Writer.Flush()
		}
	})
}

// login 处理登录请求
func (ds *DashboardServer) login(c *gin.Context) {
	var loginReq struct {
		Username string `json:"username"`
		Password string `json:"password"`
	}

	if err := c.ShouldBindJSON(&loginReq); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "无效的请求数据",
		})
		return
	}

	// 如果未设置用户名和密码，使用空值验证通过
	if loginReq.Username == ds.username && loginReq.Password == ds.password {
		// 创建JWT令牌
		expiresTime := time.Now().Add(time.Hour * 24)
		token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
			"username": loginReq.Username,
			"exp":      expiresTime.Unix(), // 24小时有效期
		})

		tokenString, err := token.SignedString(ds.jwtSecret)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"code":    500,
				"message": "生成令牌失败",
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"code":    200,
			"success": true,
			"message": "登录成功",
			"data": gin.H{
				"avatar":       "https://avatars.githubusercontent.com/u/44761321",
				"roles":        []string{"admin"},
				"permissions":  []string{"*:*:*"},
				"accessToken":  tokenString,
				"refreshToken": tokenString,
				"expires":      expiresTime.Format("2006/01/02 15:04:05"),
			},
		})
		return
	}

	c.JSON(http.StatusUnauthorized, gin.H{
		"code":    401,
		"message": "用户名或密码错误",
	})
}

// getAllClients 获取所有在线客户端
func (ds *DashboardServer) getAllClients(c *gin.Context) {
	clients := ds.clientManager.GetAllClients()
	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "success",
		"data":    clients,
	})
}

// getClientByID 根据 ID 获取客户端信息
func (ds *DashboardServer) getClientByID(c *gin.Context) {
	id := c.Param("id")
	client, ok := ds.clientManager.GetClient(id)
	if !ok {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "client not found",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "success",
		"data":    client,
	})
}

type clientStatistics struct {
	Name          string `json:"name"`
	BytesSent     int64  `json:"bytesSent"`
	BytesReceived int64  `json:"bytesReceived"`
}

// getClientsStats 获取整体统计信息
func (ds *DashboardServer) getClientsStats(c *gin.Context) {
	clients := ds.clientManager.GetAllClients()

	var cs []*clientStatistics
	for _, client := range clients {
		c := &clientStatistics{
			Name:          client.ClientAddr,
			BytesSent:     client.BytesSent,
			BytesReceived: client.BytesReceived,
		}
		cs = append(cs, c)
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "success",
		"data": gin.H{
			"totalClients":      len(clients),
			"activateClients":   len(clients),
			"clientsStatistics": cs,
		},
	})
}

// getServerInfo 获取服务器信息
func (ds *DashboardServer) getServerInfo(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "success",
		"data":    ds.serverInfo,
	})
}

// Start 启动HTTP服务器
func (ds *DashboardServer) Start() error {
	log.Infof("Dashboard server starting on port %d", ds.port)
	return ds.server.Run(":" + fmt.Sprintf("%d", ds.port))
}

// GetClientManager 获取客户端管理器，用于其他组件添加/更新客户端信息
func (ds *DashboardServer) GetClientManager() *ClientManager {
	return ds.clientManager
}
